package cn.psvmc.cxzapi.service.alipay;

import cn.psvmc.cxzapi.config.AlipayConfig;
import cn.psvmc.cxzapi.config.ConfigKey;
import cn.psvmc.cxzapi.exception.ServiceException;
import cn.psvmc.cxzapi.model.customer.TCustomer;
import cn.psvmc.cxzapi.model.goods.TGoods;
import cn.psvmc.cxzapi.model.order.TOrder;
import cn.psvmc.cxzapi.model.order.TOrderBill;
import cn.psvmc.cxzapi.model.order.TOrderDelivery;
import cn.psvmc.cxzapi.model.store.TCoupon;
import cn.psvmc.cxzapi.util.CodeUtil;
import cn.psvmc.cxzapi.util.ToolUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.FileItem;
import com.alipay.api.diagnosis.DiagnosisUtils;
import com.alipay.api.domain.*;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @Description 支付宝对接
 * @Author: YWX
 * @Date 2024/8/16 15:47
 **/
@Slf4j
public class AlipayCreate {

    private static final AlipayClient alipayClient;
    private static final String freezeNotifyUrl;

    static {
        try {
            alipayClient = AlipayConfig.getAlipayClient();
            freezeNotifyUrl = ConfigKey.notifyUrl.replaceFirst("/notify", "/freeze_notify");
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @Description 租赁商品场景-订单创建
     * @Date 2024/8/16 16:19
     * @Author YWX
     * @Param []
     * @Return void
     **/
    public static AlipayOpenMiniOrderCreateResponse alipayOpenMiniOrderCreate(TOrder order, TCustomer customer, List<TOrderBill> bills
            , TGoods tGoods, String goodsSpecsName, Map<String, String> store) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));
            AlipayOpenMiniOrderCreateRequest request = new AlipayOpenMiniOrderCreateRequest();
            request.setNotifyUrl(ConfigKey.notifyUrl);
            AlipayOpenMiniOrderCreateModel model = new AlipayOpenMiniOrderCreateModel();
            //商户订单号，由商家自定义，64个字符以内，仅支持字母、数字、下划线且需保证在商户端不重复
            model.setOutOrderId(order.getOrderCode());
            //订单标题
            String goodsName = tGoods.getName();
            model.setTitle(goodsName + goodsSpecsName);
            model.setBuyerOpenId(customer.getOpenid());
            //model.setTimeoutExpress("1h");
            //model.setConfirmTimeoutExpress("5d");
            model.setSourceId(order.getSourceId());
            //订单类型，决定后续履约节点中的参数校验规则，必填。标准租赁场景固定为STANDARD_RENT。
            model.setMerchantBizType("STANDARD_RENT");
            //商家小程序对应的订单详情页路径地址
            model.setPath("/pages_b/order/order_detail?orderId=" + order.getOrderId());

            //买家联系人信息-可选
            ContactInfoDTO contactInfo = new ContactInfoDTO();
            contactInfo.setPhoneNumber(customer.getPhone());
            contactInfo.setContactName(customer.getRealName());
            model.setContactInfo(contactInfo);

            //订单收货地址，标准租赁场景必传。
            MiniReceiverAddressInfoDTO addressInfo = new MiniReceiverAddressInfoDTO();
            addressInfo.setReceiverName(order.getUsername());
            addressInfo.setDetailedAddress(order.getUserAddress());
            addressInfo.setTelNumber(order.getUserphone());
            model.setAddressInfo(addressInfo);

            //订单信息
            MiniOrderDetailDTO orderDetail = new MiniOrderDetailDTO();
            //商品详细信息
            List<MiniGoodsDetailInfoDTO> itemInfos = new ArrayList<>();
            MiniGoodsDetailInfoDTO itemInfos0 = new MiniGoodsDetailInfoDTO();
            //商品名称
            itemInfos0.setGoodsName(goodsName);
            //商品数量
            itemInfos0.setItemCnt(ToolUtils.objToString(order.getNum()));
            //商品单价，单位：元，精确到小数点后两位，注：租赁商品请传入日租金，如10元/天
            itemInfos0.setSalePrice(ToolUtils.objToString(ToolUtils.divideAndCeil(order.getRent(), order.getDay())));
            String itemDiscount = ToolUtils.objToString(ToolUtils.subtract(order.getRent(), order.getRentAfterCoupon()));
            itemInfos0.setItemDiscount(itemDiscount);
            //提报支付券优惠时的商品id，用于关联使用支付券，需要和支付券上绑定商品goods_id相同。如果不使用支付券，该字段传入商品最小粒度的商品id（如：若商品有 sku 粒度，则传商品 sku 粒度的id）
            itemInfos0.setGoodsId(tGoods.getGoodsCode());
            itemInfos0.setOutSkuId(ToolUtils.objToString(order.getGsid()));

            if (order.getAddType().equals(2)) {//快捷下单
                itemInfos0.setOutItemId(tGoods.getGoodsCode());

                //PayInfoDTO payInfo = new PayInfoDTO();
                //payInfo.setPaymentMethod("NO_NEED_TO_PAY");
                //orderDetail.setPayInfo(payInfo);

                FundAuthFreezeInfoDTO authFreezeInfo = new FundAuthFreezeInfoDTO();
                authFreezeInfo.setFreezeNotifyUrl(AlipayCreate.freezeNotifyUrl);
                authFreezeInfo.setZmServiceId(ConfigKey.serviceId);
                authFreezeInfo.setCategoryId("RENT_COMPUTER");
                model.setFundAuthFreezeInfo(authFreezeInfo);
            }

            Long periodNum = ToolUtils.objToLong(order.getLeasePeriod());
            String orderPrice = ToolUtils.objToString(order.getRent());

            //租金信息，租赁商品特有
            RentInfoDTO rentInfo = new RentInfoDTO();
            // 设置租赁开始时间
            rentInfo.setRentStartTime(sdf.parse(order.getPlanBegin().format(dtf)));
            // 设置租赁结束时间
            rentInfo.setRentEndTime(sdf.parse(order.getPlanEnd().format(dtf)));
            // 设置初始租金价格
            rentInfo.setInitialRentPrice(orderPrice);
            // 设置周期实际租金价格
            rentInfo.setPeriodRealRentPrice(ToolUtils.objToString(order.getRentAfterCoupon()));
            // 设置租赁周期数量
            rentInfo.setPeriodNum(periodNum);
            // 设置买断价格
            Double orderBuyPrice = order.getBuyPrice();
            if (orderBuyPrice.compareTo(0.0) > 0) {
                rentInfo.setBuyoutPrice(ToolUtils.objToString(orderBuyPrice));
            }
            // 设置押金价格
            rentInfo.setDepositPrice(ToolUtils.objToString(order.getDeposit()));
            // 将租赁信息设置到项目信息中
            itemInfos0.setRentInfo(rentInfo);

            //商品分期信息（分期代扣商品必填）
            ItemInstallmentInfoDTO itemInstallmentInfo = new ItemInstallmentInfoDTO();
            //总分期数
            itemInstallmentInfo.setPeriodNum(periodNum);
            //分期商品每期金额不固定时，请填入该字段，分期时分期金额会与该字段进行比较，单位为元
            itemInstallmentInfo.setPeriodMaxPrice(ToolUtils.objToString(order.getRentAfterCoupon()));
            itemInfos0.setItemInstallmentInfo(itemInstallmentInfo);
            itemInfos.add(itemInfos0);
            orderDetail.setItemInfos(itemInfos);

            //价格详细信息-必选
            PriceInfoDTO priceInfo = new PriceInfoDTO();
            //订单总价，单位：元,精确到小数点后两位
            priceInfo.setOrderPrice(orderPrice);
            //运费，单位：元，精确到小数点后两位
            priceInfo.setFreight(ToolUtils.objToString(order.getShippingFee()));
            //商家优惠金额，单位：元，精确到小数点后两位
            priceInfo.setDiscountedPrice(itemDiscount);
            orderDetail.setPriceInfo(priceInfo);
            model.setOrderDetail(orderDetail);

            //阶段付款计划，租赁场景或分期代扣场景，该字段必填
            List<StagePayPlanDTO> stagePayPlans = new ArrayList<>();
            StagePayPlanDTO stagePayPlans0 = new StagePayPlanDTO();
            //阶段付款计划阶段编号，标识当前计划处于第几阶段，起始值为1，多阶段需保证阶段编号递增
            Long stageNo = 1L;
            stagePayPlans0.setStageNo(stageNo);
            //阶段付款计划详情列表
            List<StagePayPlanInfoDTO> stagePayPlanInfos = new ArrayList<>();
            for (TOrderBill bill : bills) {
                StagePayPlanInfoDTO stagePayPlanInfos0 = new StagePayPlanInfoDTO();
                //阶段计划付款编号，标识第几次或第几期付款，起始值为1，多个计划需保证编号递增
                stagePayPlanInfos0.setPlanPayNo(stageNo);
                //阶段付款计划付款金额，单位：元，精确到小数点后两位
                stagePayPlanInfos0.setPlanPayPrice(ToolUtils.objToString(bill.getPayAmount()));
                //阶段付款计划付款时间，多个计划需保证付款时间递增
                stagePayPlanInfos0.setPlanPayTime(sdf.parse(bill.getBeginTime().format(dtf)));
                stagePayPlanInfos.add(stagePayPlanInfos0);
                stageNo++;
            }
            stagePayPlans0.setStagePayPlanInfos(stagePayPlanInfos);
            stagePayPlans.add(stagePayPlans0);
            model.setStagePayPlans(stagePayPlans);

            //门店信息
            ShopInfoDTO shopInfo = new ShopInfoDTO();
            shopInfo.setName(store.get("storename"));
            shopInfo.setAddress(store.get("storeaddress"));
            model.setShopInfo(shopInfo);

            /*AllocAmountInfoDTO allocAmountInfo = new AllocAmountInfoDTO();
            allocAmountInfo.setInvestId("4442222311");
            RoyaltyDTO royaltyDTO = new RoyaltyDTO();
            royaltyDTO.setRoyaltyType("BUYOUT");
            allocAmountInfo.setBuyOutRoyalty(royaltyDTO);

            List<RentRoyaltyDetailDTO> rentRoyaltyDetailDTOS = new ArrayList<>();
            RentRoyaltyDetailDTO rentRoyaltyDetailDTO = new RentRoyaltyDetailDTO();
            rentRoyaltyDetailDTO.setStageNo(1L);
            List<RoyaltyDTO> royaltyDTOS = new ArrayList<>();
            RoyaltyDTO royaltyDTO1 = new RoyaltyDTO();
            String royaltyType = "RENT";
            if (order.getOrderType().equals(2)) {
                royaltyType = "BUYOUT";
            }
            royaltyDTO1.setRoyaltyPrice(ToolUtils.objToString(order.getRentAfterCoupon()));
            royaltyDTO1.setRoyaltyPeriod(Long.valueOf(order.getLeasePeriod()));
            royaltyDTO1.setRoyaltyType(royaltyType);
            royaltyDTOS.add(royaltyDTO1);
            rentRoyaltyDetailDTO.setRoyalties(royaltyDTOS);
            allocAmountInfo.setRentRoyaltyDetails(rentRoyaltyDetailDTOS);*/

            // 执行支付宝小程序订单创建请求
            request.setBizModel(model);
            AlipayOpenMiniOrderCreateResponse response = AlipayCreate.alipayClient.certificateExecute(request);

            if (response.isSuccess()) {
                AlipayCreate.log.info("租赁商品场景-订单创建调用成功，返回值：{}", JSON.toJSONString(response));
                return response;
            } else {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("租赁商品场景-订单创建调用失败, 诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
        } catch (Exception e) {
            AlipayCreate.log.error("租赁商品场景-订单创建调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 租赁商品场景-订单修改
     * @Date 2024/12/20 23:21
     * @Author YWX
     * @Param [order, bills]
     * @Return com.alipay.api.response.AlipayOpenMiniOrderModifyResponse
     **/
    public static void orderModify(String orderCode, String openId, List<TOrderBill> bills) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));
            AlipayOpenMiniOrderModifyRequest request = new AlipayOpenMiniOrderModifyRequest();
            AlipayOpenMiniOrderModifyModel model = new AlipayOpenMiniOrderModifyModel();
            //商户订单号，由商家自定义，64个字符以内，仅支持字母、数字、下划线且需保证在商户端不重复
            model.setOutOrderId(orderCode);
            model.setOpenId(openId);

            // 设置订单价格信息
            PriceInfoModifyDTO priceInfo = new PriceInfoModifyDTO();
            priceInfo.setOrderPrice(ToolUtils.formatDouble(bills.stream().mapToDouble(TOrderBill::getPayAmount).sum()));
            model.setPriceInfo(priceInfo);

            //阶段付款计划，租赁场景或分期代扣场景，该字段必填
            List<StagePayPlanDTO> stagePayPlans = new ArrayList<>();
            Map<Long, List<TOrderBill>> collect = bills.stream().collect(Collectors.groupingBy(TOrderBill::getStageNo));
            for (Map.Entry<Long, List<TOrderBill>> entry : collect.entrySet()) {
                Long planPayNo = 1L;
                StagePayPlanDTO stagePayPlans0 = new StagePayPlanDTO();
                //阶段付款计划阶段编号，标识当前计划处于第几阶段，起始值为1，多阶段需保证阶段编号递增
                Long stageNo = entry.getKey();
                stagePayPlans0.setStageNo(stageNo);
                //阶段付款计划详情列表
                List<StagePayPlanInfoDTO> stagePayPlanInfos = new ArrayList<>();
                for (TOrderBill bill : entry.getValue()) {
                    StagePayPlanInfoDTO stagePayPlanInfos0 = new StagePayPlanInfoDTO();
                    //阶段计划付款编号，标识第几次或第几期付款，起始值为1，多个计划需保证编号递增
                    stagePayPlanInfos0.setPlanPayNo(planPayNo);
                    planPayNo++;
                    //阶段付款计划付款金额，单位：元，精确到小数点后两位
                    stagePayPlanInfos0.setPlanPayPrice(ToolUtils.objToString(bill.getPayAmount()));
                    //阶段付款计划付款时间，多个计划需保证付款时间递增
                    stagePayPlanInfos0.setPlanPayTime(sdf.parse(bill.getBeginTime().format(dtf)));
                    stagePayPlanInfos.add(stagePayPlanInfos0);
                }
                stagePayPlans0.setStagePayPlanInfos(stagePayPlanInfos);
                stagePayPlans.add(stagePayPlans0);
            }
            model.setStagePayPlans(stagePayPlans);

            // 执行支付宝小程序订单修改请求
            request.setBizModel(model);
            AlipayOpenMiniOrderModifyResponse response = AlipayCreate.alipayClient.certificateExecute(request);

            AlipayCreate.log.info("租赁商品场景-订单修改调用成功，返回值：{}", JSON.toJSONString(response));
            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("租赁商品场景-订单修改调用失败, 诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
        } catch (Exception e) {
            AlipayCreate.log.error("租赁商品场景-订单修改调用失败：{}", e.getMessage());
            if (!"参数有误不存在租赁单".equals(e.getMessage())) throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 履约状态变更
     * 商家已确认: MERCHANT_CONFIRMED
     * 已归还: RETURNED
     * 租完即送: RENT_OVER_SEND
     * @Date 2024/12/10 12:42
     * @Author YWX
     * @Param [orderCode, openId, status]
     * @Return void
     **/
    public static void deliveryModify(String orderCode, String openId, String status) {
        // 构造请求参数以调用接口
        AlipayOpenMiniOrderDeliveryModifyRequest request = new AlipayOpenMiniOrderDeliveryModifyRequest();
        AlipayOpenMiniOrderDeliveryModifyModel model = new AlipayOpenMiniOrderDeliveryModifyModel();

        // 设置商户订单号
        model.setOutOrderId(orderCode);
        // 设置支付宝用户open_id
        model.setOpenId(openId);
        model.setStatus(status);

        request.setBizModel(model);

        try {
            AlipayOpenMiniOrderDeliveryModifyResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("履约状态变更调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("履约状态变更调用失败, 诊断链接：{}", diagnosisUrl);
            }
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("履约状态变更调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 订单发货
     * @Date 2024/12/10 13:09
     * @Author YWX
     * @Param [delivery, gd]
     * @Return void
     **/
    public static void deliverySend(TOrderDelivery delivery, GoodsDetail gd) {
        // 构造请求参数以调用接口
        AlipayOpenMiniOrderDeliverySendRequest request = new AlipayOpenMiniOrderDeliverySendRequest();
        AlipayOpenMiniOrderDeliverySendModel model = new AlipayOpenMiniOrderDeliverySendModel();

        // 设置商户订单号
        model.setOutOrderId(delivery.getOrderCode());
        // 设置支付宝用户open_id
        model.setOpenId(delivery.getOpenid());
        Integer deliveryType = delivery.getDeliveryType();
        if (!deliveryType.equals(99)) {
            delivery.setTrackingCode("990000000000000");
        }
        List<DeliveryInfoDTO> deliveryInfos = new ArrayList<>();
        DeliveryInfoDTO deliveryInfo = new DeliveryInfoDTO();
        String deliveryId = "other";
        if (deliveryType.equals(1)) {
            deliveryId = "SF";//顺丰速运
            //deliveryId = "SFISTD";//顺丰同城
        } else if (deliveryType.equals(2)) {
            //deliveryId = "DBL";//德邦
            deliveryId = "DBKD";//德邦快递
        }
        deliveryInfo.setDeliveryId(deliveryId);
        deliveryInfo.setWaybillId(delivery.getTrackingCode());
        List<GoodsItemDTO> goodsItems = new ArrayList<>();
        GoodsItemDTO goodsItem = new GoodsItemDTO();
        goodsItem.setOutItemId(gd.getGoodsId());//商户商品ID
        goodsItem.setItemCnt(gd.getQuantity());//商品数量
        goodsItem.setOutSkuId(gd.getOutSkuId());//商户商品sku_id
        goodsItem.setGoodsId(gd.getGoodsId());//商户侧商品的编号，应与alipay.open.mini.order.create接口所传的商品goods_id保持一致
        goodsItems.add(goodsItem);
        deliveryInfo.setItemInfoList(goodsItems);
        deliveryInfos.add(deliveryInfo);
        model.setDeliveryList(deliveryInfos);
        long finishAllDelivery = 0L;
        String acceptTime = delivery.getAcceptTime();
        if (ToolUtils.isNotEmpty(acceptTime)) {
            finishAllDelivery = 1L;
            model.setShipDoneTime(acceptTime);
        }
        model.setFinishAllDelivery(finishAllDelivery);

        request.setBizModel(model);

        try {
            AlipayOpenMiniOrderDeliverySendResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("订单发货调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("订单发货调用失败, 诊断链接：{}", diagnosisUrl);
            }
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("订单发货调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 订单确认收货
     * @Date 2024/12/10 13:12
     * @Author YWX
     * @Param [orderCode, openId]
     * @Return void
     **/
    public static void deliveryReceive(String orderCode, String openId) {
        // 构造请求参数以调用接口
        AlipayOpenMiniOrderDeliveryReceiveRequest request = new AlipayOpenMiniOrderDeliveryReceiveRequest();
        AlipayOpenMiniOrderDeliveryReceiveModel model = new AlipayOpenMiniOrderDeliveryReceiveModel();

        // 设置商户订单号
        model.setOutOrderId(orderCode);
        // 设置支付宝用户open_id
        model.setOpenId(openId);

        request.setBizModel(model);

        try {
            AlipayOpenMiniOrderDeliveryReceiveResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("订单确认收货调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("订单确认收货调用失败, 诊断链接：{}", diagnosisUrl);
            }
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("订单确认收货调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 订单关闭
     * @Date 2024/12/10 23:11
     * @Author YWX
     * @Param [orderCode]
     * @Return void
     **/
    public static void orderClose(String orderCode, String openId) {
        // 构造请求参数以调用接口
        AlipayOpenMiniOrderCloseRequest request = new AlipayOpenMiniOrderCloseRequest();
        AlipayOpenMiniOrderCloseModel model = new AlipayOpenMiniOrderCloseModel();

        // 设置商户订单号
        model.setOutOrderId(orderCode);
        model.setOpenId(openId);

        request.setBizModel(model);

        try {
            AlipayOpenMiniOrderCloseResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("订单关闭调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("订单关闭调用失败, 诊断链接：{}", diagnosisUrl);
            }
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("订单关闭调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 查询订单
     * @Date 2024/9/30 8:51
     * @Author YWX
     * @Param [orderCode, openId]
     * @Return void
     **/
    public static AlipayOpenMiniOrderQueryResponse alipayOpenMiniOrderQuery(String orderCode, String openId) {
        // 构造请求参数以调用接口
        AlipayOpenMiniOrderQueryRequest request = new AlipayOpenMiniOrderQueryRequest();
        AlipayOpenMiniOrderQueryModel model = new AlipayOpenMiniOrderQueryModel();

        // 设置商户订单号
        model.setOutOrderId(orderCode);
        // 设置支付宝用户open_id
        model.setOpenId(openId);

        request.setBizModel(model);

        try {
            AlipayOpenMiniOrderQueryResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("查询订单调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("查询订单调用失败, 诊断链接：{}", diagnosisUrl);
            }
            return response;
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("查询订单调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 查询订单对账列表
     * @Date 2024/9/30 9:19
     * @Author YWX
     * @Param [model]
     * @Return void
     **/
    public static AlipayOpenMiniOrderItembillBatchqueryResponse alipayOpenMiniOrderItembillBatchquery(AlipayOpenMiniOrderItembillBatchqueryModel model) {
        // 构造请求参数以调用接口
        AlipayOpenMiniOrderItembillBatchqueryRequest request = new AlipayOpenMiniOrderItembillBatchqueryRequest();

        // 设置小程序应用ID
        model.setMiniAppId(ConfigKey.appId);
        /*AlipayOpenMiniOrderItembillBatchqueryModel model = new AlipayOpenMiniOrderItembillBatchqueryModel();

        // 设置账单类型列表
        List<String> serviceTypeList = new ArrayList<>();
        serviceTypeList.add("PHYSICAL_ITEM");
        serviceTypeList.add("MEMBER_ITEM");
        model.setServiceTypeList(serviceTypeList);

        // 设置订单结算时间
        model.setSettlementDate("2023-03-22");

        // 设置订单创建时间
        model.setCreateTime("2023-03-22");

        // 设置支付宝交易号
        model.setTradeNo("2013112011001004330000121536");

        // 设置订单状态
        model.setOrderStatus("INIT");

        // 设置结算状态
        model.setSettleStatus("UN_SETTLE");

        // 设置分页页码
        model.setPageNum(1L);

        // 设置分页大小
        model.setPageSize(10L);*/

        request.setBizModel(model);

        try {
            AlipayOpenMiniOrderItembillBatchqueryResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("查询订单对账列表调用成功，返回值：{}", response.getBody());

            if (response.isSuccess()) {
                return response;
            } else {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("查询订单对账列表调用失败, 诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("查询订单对账列表调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description status: 订单履约状态变更（已确认: MERCHANT_CONFIRMED 已归还: RETURNED)
     * @Date 2024/9/28 0:44
     * @Author YWX
     * @Param [orderCode, openId, status]
     * @Return void
     **/
    public static void alipayOpenMiniOrderDeliveryModify(String orderCode, String openId, String status) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));

        // 构造请求参数以调用接口
        AlipayOpenMiniOrderDeliveryModifyRequest request = new AlipayOpenMiniOrderDeliveryModifyRequest();
        AlipayOpenMiniOrderDeliveryModifyModel model = new AlipayOpenMiniOrderDeliveryModifyModel();

        // 设置商户订单号
        model.setOutOrderId(orderCode);
        // 设置用户openId
        model.setOpenId(openId);
        // 设置履约推进状态
        model.setStatus(status);
        request.setBizModel(model);

        try {
            AlipayOpenMiniOrderDeliveryModifyResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("订单履约状态变更调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("订单履约状态变更调用失败, 诊断链接：{}", diagnosisUrl);
            }
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("订单履约状态变更调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 订单关闭
     * @Date 2024/9/28 1:03
     * @Author YWX
     * @Param [orderCode, openId]
     * @Return void
     **/
    public static void alipayOpenMiniOrderClose(String orderCode, String openId) {
        // 构造请求参数以调用接口
        AlipayOpenMiniOrderCloseRequest request = new AlipayOpenMiniOrderCloseRequest();
        AlipayOpenMiniOrderCloseModel model = new AlipayOpenMiniOrderCloseModel();

        // 设置用户open_id
        model.setOpenId(openId);
        // 设置商户订单号
        model.setOutOrderId(orderCode);

        request.setBizModel(model);
        try {
            AlipayOpenMiniOrderCloseResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("订单关闭调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("订单关闭调用失败, 诊断链接：{}", diagnosisUrl);
            }
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("订单关闭调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 统一收单交易退款
     * @Date 2024/9/28 13:02
     * @Author YWX
     * @Param [orderCode, tradeNo, amount]
     * @Return void
     **/
    public static AlipayTradeRefundResponse alipayTradeRefund(String orderCode, String tradeNo, Double amount) {
        // 构造请求参数以调用接口
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();

        // 设置商户订单号
        model.setOutTradeNo(orderCode);

        // 设置支付宝交易号
        model.setTradeNo(tradeNo);

        // 设置退款金额
        model.setRefundAmount(ToolUtils.objToString(amount));

        // 设置退款原因说明
        model.setRefundReason("正常退款");

        request.setBizModel(model);

        try {
            AlipayTradeRefundResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("统一收单交易退款调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("统一收单交易退款调用失败, 诊断链接：{}", diagnosisUrl);
                if (!response.getSubMsg().contains("交易不存在")) {
                    throw new ServiceException(response.getSubMsg());
                }
            }
            return response;
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("统一收单交易退款调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 部分退款
     * @Date 2024/10/31 22:13
     * @Author YWX
     * @Param [orderCode, tradeNo, amount, outRequestNo]
     * @Return com.alipay.api.response.AlipayTradeRefundResponse
     **/
    public static AlipayTradeRefundResponse alipayTradeRefund2(String orderCode, String tradeNo, Double amount) {
        // 构造请求参数以调用接口
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();

        // 设置商户订单号
        model.setOutTradeNo(orderCode);

        // 设置支付宝交易号
        model.setTradeNo(tradeNo);

        // 设置退款金额
        model.setRefundAmount(ToolUtils.objToString(amount));
        model.setOutRequestNo(CodeUtil.generateOuterOrderNo());

        // 设置退款原因说明
        model.setRefundReason("正常退款");

        request.setBizModel(model);

        try {
            AlipayTradeRefundResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("统一收单交易部分退款调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("统一收单交易部分退款调用失败, 诊断链接：{}", diagnosisUrl);
            }
            return response;
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("统一收单交易部分退款调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }


    /**
     * @Description 线上资金授权冻结
     * @Date 2024/9/21 13:45
     * @Author YWX
     * @Param [order, goods]
     * @Return java.lang.String
     **/
    public static AlipayFundAuthOrderAppFreezeResponse alipayFundAuthOrderAppFreeze(TOrder order, TGoods tGoods) {
        String orderCode = order.getOrderCode();
        Double deposit = order.getDeposit();
        // 构造请求参数以调用接口
        AlipayFundAuthOrderAppFreezeRequest request = new AlipayFundAuthOrderAppFreezeRequest();
        request.setNotifyUrl(ConfigKey.notifyUrl);
        AlipayFundAuthOrderAppFreezeModel model = new AlipayFundAuthOrderAppFreezeModel();

        // 设置订单标题
        String goodsName = tGoods.getName();
        model.setOrderTitle(goodsName + "押金");

        // 设置需要冻结的金额
        model.setAmount(ToolUtils.objToString(deposit));

        // 设置收款账户的支付宝用户号
        //model.setPayeeUserId("2088102000275795");

        // 设置商户授权资金订单号
        model.setOutOrderNo(orderCode);
        model.setOutRequestNo(orderCode);

        // 设置销售产品码
        //model.setProductCode("PRE_AUTH_ONLINE");
        model.setProductCode("PREAUTH_PAY");

        // 设置收款账户的支付宝登录号（email或手机号）
        /*model.setPayeeLogonId("159****5620");

        // 设置无特殊需要请勿传入
        model.setEnablePayChannels("[{\"payChannelType\":\"PCREDIT_PAY\"},{\"payChannelType\":\"MONEY_FUND\"}]");

        // 设置免押受理台模式
        model.setDepositProductMode("POSTPAY");

        // 设置无特殊需要请勿传入
        model.setIdentityParams("{\"identity_hash\":\"acc2b92ffc5ed9b472faa19748f10045c30434132784f774b00216a56b8841c6\"}");

        // 设置业务参数
        model.setBusinessParams("{\"outRiskInfo\":\"{\"mcCreateTradeTime\":\"2022-03-11 12:46:09\",\"extraAccountCertnoLastSix\":\"000011\",\"mobileOperatingPlatform\":\"ios\",\"sysVersion\":\"15.4.2\",\"mcCreateTradeIp\":\"11.110.111.43\"}\"}");

        // 设置预授权订单相对超时时间
        model.setTimeoutExpress("2d");

        // 设置无特殊需要请勿传入
        model.setDisablePayChannels("[{\"payChannelType\":\"OPTIMIZED_MOTO\"},{\"payChannelType\":\"BIGAMOUNT_CREDIT_CARTOON\"}]");

        // 设置商户本次资金操作的请求流水号
        model.setOutRequestNo("8077735255938032");*/

        //model.setExtraParam("{\"category\":\"RENT_COMPUTER\",\"serviceId\":\"" + ConfigKey.serviceId + "\"}");
        // 设置业务扩展参数(https://www.yuque.com/u28154685/zv3alp/uzho5np7xkaxsrth)
        JSONObject extraParams = new JSONObject();
        extraParams.put("category", "RENT_COMPUTER");
        extraParams.put("serviceId", ConfigKey.serviceId);

        JSONObject creditExtInfo = new JSONObject();
        creditExtInfo.put("carrierDesc", goodsName);//商品标题
        creditExtInfo.put("rentPeriod", order.getDay());//订单租期：本次请求的订单租期，比如7，15，360等，以天为单位
        creditExtInfo.put("rentAmount", order.getRentAfterCoupon());//本次请求的订单总租金金额
        creditExtInfo.put("deliveryAddress", order.getUserAddress());//收货地址
        creditExtInfo.put("deliveryMobile", order.getUserphone());//收货手机号
        creditExtInfo.put("deliveryName", order.getUsername());//收货人姓名
        creditExtInfo.put("riskSchemeId", ConfigKey.riskSchemeId);//评估方案ID
        creditExtInfo.put("assessmentAmount", ToolUtils.objToString(ToolUtils.truncate(deposit * 0.2)));//押金评估金额
        creditExtInfo.put("rentGoodsId", tGoods.getGoodsCode());
        extraParams.put("creditExtInfo", creditExtInfo);
        extraParams.put("trade_component_order_id", order.getTradeComponentOrderId());
        model.setExtraParam(extraParams.toString());

        model.setDepositProductMode("DEPOSIT_ONLY");
        request.setBizModel(model);
        // 第三方代调用模式下请设置app_auth_token
        // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");

        String orderStr = null;
        try {
            AlipayFundAuthOrderAppFreezeResponse response = AlipayCreate.alipayClient.sdkExecute(request);
            orderStr = response.getBody();

            AlipayCreate.log.info("线上资金授权冻结调用成功，返回值：{}", orderStr);
            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("线上资金授权冻结调用失败, 诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
            return response;
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("线上资金授权冻结调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 资金授权撤销接口
     * @Date 2024/9/24 21:54
     * @Author YWX
     * @Param [orderCode]
     * @Return void
     **/
    public static void alipayFundAuthOperationCancel(String orderCode) {
        boolean result = false;
        // 构造请求参数以调用接口
        AlipayFundAuthOperationCancelRequest request = new AlipayFundAuthOperationCancelRequest();
        request.setNotifyUrl(ConfigKey.notifyUrl);
        AlipayFundAuthOperationCancelModel model = new AlipayFundAuthOperationCancelModel();

        // 设置支付宝授权资金订单号
        //model.setAuthNo("2014070800002001550000014417");

        // 设置商户的授权资金订单号
        model.setOutOrderNo(orderCode);

        // 设置支付宝的授权资金操作流水号
        //model.setOperationId("20161012405744018102");

        // 设置商户的授权资金操作流水号
        model.setOutRequestNo(orderCode);

        // 设置商户对本次撤销操作的附言描述
        model.setRemark("授权撤销");

        request.setBizModel(model);
        // 第三方代调用模式下请设置app_auth_token
        // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");

        try {
            AlipayFundAuthOperationCancelResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("线上资金授权撤销调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("线上资金授权撤销调用失败, 诊断链接：{}", diagnosisUrl);
            } else {
                result = true;
            }
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("线上资金授权撤销调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 资金授权操作查询
     * @Date 2024/9/24 23:14
     * @Author YWX
     * @Param [orderCode]
     * @Return void
     **/
    public static AlipayFundAuthOperationDetailQueryResponse alipayFundAuthOperationDetailQuery(String orderCode) {
        // 构造请求参数以调用接口
        AlipayFundAuthOperationDetailQueryRequest request = new AlipayFundAuthOperationDetailQueryRequest();
        AlipayFundAuthOperationDetailQueryModel model = new AlipayFundAuthOperationDetailQueryModel();

        // 设置需要查询的授权资金操作类型
        model.setOperationType("FREEZE");

        // 设置商户的授权资金订单号
        model.setOutOrderNo(orderCode);

        // 设置支付宝的授权资金操作流水号
        //model.setOperationId("20140216010020006400");

        // 设置商户的授权资金操作流水号
        model.setOutRequestNo(orderCode);
        List<String> queryOptions = new ArrayList<>();
        queryOptions.add("credit_risk_info");
        model.setQueryOptions(queryOptions);

        // 设置支付宝授权资金订单号
        //model.setAuthNo("2014021601002000640012345678");

        request.setBizModel(model);
        try {
            AlipayFundAuthOperationDetailQueryResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("线上资金授权操作查询调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("线上资金授权操作查询调用失败, 诊断链接：{}", diagnosisUrl);
            }
            return response;
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("线上资金授权操作查询调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 资金授权解冻
     * @Date 2024/9/25 0:06
     * @Author YWX
     * @Param [orderCode, amount]
     * @Return void
     **/
    public static void alipayFundAuthOrderUnfreeze(String authNo, Double amount) {
        if (ToolUtils.isEmpty(authNo)) {
            return;
        }
        boolean result = false;
        // 构造请求参数以调用接口
        AlipayFundAuthOrderUnfreezeRequest request = new AlipayFundAuthOrderUnfreezeRequest();
        request.setNotifyUrl(ConfigKey.notifyUrl);
        JSONObject bizContent = new JSONObject();

        bizContent.put("auth_no", authNo);
        bizContent.put("out_request_no", CodeUtil.generateBillSequence());
        bizContent.put("amount", amount);
        bizContent.put("remark", "解冻资金");

        JSONObject extraParam = new JSONObject();
        JSONObject unfreezeBizInfo = new JSONObject();
        unfreezeBizInfo.put("bizComplete", true);
        extraParam.put("unfreezeBizInfo", unfreezeBizInfo);
        bizContent.put("extra_param", extraParam);

        // 设置整体请求参数
        request.setBizContent(bizContent.toString());
        try {
            AlipayFundAuthOrderUnfreezeResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("资金授权解冻调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                AlipayCreate.log.error("资金授权解冻调用失败");
            } else {
                result = true;
            }
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("资金授权解冻调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 统一收单交易创建 https://opendocs.alipay.com/mini/6039ed0c_alipay.trade.create?pathHash=779dc517&scene=de4d6a1e0c6e423b9eefa7c3a6dcb7a5
     * @Date 2024/8/31 21:00
     * @Author YWX
     * @Param [model]
     * @Return void
     **/
    public static AlipayTradeCreateResponse AlipayTradeCreate(AlipayTradeCreateModel model) {
        // 构造请求参数以调用接口
        AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
        request.setNotifyUrl(ConfigKey.notifyUrl);
        /*AlipayTradeCreateModel model = new AlipayTradeCreateModel();

        // 设置商户订单号
        model.setOutTradeNo("20150320010101001");

        // 设置产品码
        model.setProductCode("JSAPI_PAY");

        // 设置小程序支付中
        model.setOpAppId("2014072300007148");

        // 设置订单总金额
        model.setTotalAmount("88.88");

        // 设置业务扩展参数
        ExtendParams extendParams = new ExtendParams();
        extendParams.setTradeComponentOrderId("2023060801502300000008810000005657");
        model.setExtendParams(extendParams);

        // 设置可打折金额
        model.setDiscountableAmount("80.00");

        // 设置订单标题
        model.setSubject("Iphone6 16G");

        // 设置订单附加信息
        model.setBody("Iphone6 16G");

        // uid参数未来计划废弃，存量商户可继续使用，新商户请使用openid。请根据应用-开发配置-openid配置选择支持的字段。
        // model.setBuyerId("2088102146225135");

        // 设置买家支付宝用户唯一标识
        model.setBuyerOpenId("074a1CcTG1LelxKe4xQC0zgNdId0nxi95b5lsNpazWYoCo5");

        // 设置商户门店编号
        model.setStoreId("NJ_001");*/

        model.setOpAppId(ConfigKey.appId);
        request.setBizModel(model);
        // 第三方代调用模式下请设置app_auth_token
        // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");

        try {
            AlipayTradeCreateResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            if (!response.isSuccess()) {
                throw new ServiceException(response.getSubMsg());
            }
            return response;
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("统一收单交易创建失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 统一收单交易查询
     * @Date 2024/9/30 0:14
     * @Author YWX
     * @Param [orderCode, tradeNo]
     * @Return void
     **/
    public static AlipayTradeQueryResponse alipayTradeQuery(String orderCode, String tradeNo) {
        // 构造请求参数以调用接口
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();

        // 设置订单支付时传入的商户订单号
        model.setOutTradeNo(orderCode);

        // 设置支付宝交易号
        model.setTradeNo(tradeNo);

        // 设置查询选项
        List<String> queryOptions = new ArrayList<>();
        queryOptions.add("trade_settle_info");
        queryOptions.add("fund_bill_list");
        model.setQueryOptions(queryOptions);

        request.setBizModel(model);

        try {
            AlipayTradeQueryResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("统一收单交易查询调用成功，返回值：{}", JSON.toJSONString(response));

            return response;
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("统一收单交易查询调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 统一收单交易关闭
     * @Date 2024/9/28 15:37
     * @Author YWX
     * @Param [tradeNo]
     * @Return void
     **/
    public static AlipayTradeCloseResponse alipayTradeClose(String orderCode, String tradeNo) {
        AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
        //request.setNotifyUrl(ConfigKey.notifyUrl);
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", orderCode);
        bizContent.put("trade_no", tradeNo);
        request.setBizContent(bizContent.toString());
        try {
            AlipayTradeCloseResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("统一收单交易关闭调用成功，返回值：{}", JSON.toJSONString(response));
            if (!response.isSuccess()) {
                AlipayCreate.log.error("统一收单交易关闭调用失败：{}", response.getSubMsg());
                //throw new ServiceException(response.getSubMsg());
            }
            return response;
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("统一收单交易关闭调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }


    /**
     * @Description 订单分期 https://opendocs.alipay.com/mini/2cce2a35_alipay.open.mini.order.installment.create
     * @Date 2024/8/31 21:02
     * @Author YWX
     * @Param [model]
     * @Return void
     **/
    public static AlipayOpenMiniOrderInstallmentCreateResponse orderInstallmentCreate(TOrderBill bill, String openId, String type, Boolean isSyncPay) {
        // 构造请求参数以调用接口
        AlipayOpenMiniOrderInstallmentCreateRequest request = new AlipayOpenMiniOrderInstallmentCreateRequest();
        request.setNotifyUrl(ConfigKey.notifyUrl);
        AlipayOpenMiniOrderInstallmentCreateModel model = new AlipayOpenMiniOrderInstallmentCreateModel();

        // 设置支付宝用户唯一标识
        model.setOpenId(openId);

        // 设置是否同步主动支付
        model.setIsSyncPay(isSyncPay);

        // 设置分期号类型
        model.setInstallmentNoType("PERIOD");

        // 设置分期类型
        model.setType(type);

        // 设置本次分期号
        model.setInstallmentNo(ToolUtils.objToString(bill.getInstallmentNo()));

        // 设置分期金额
        model.setInstallmentPrice(ToolUtils.objToString(bill.getPayAmount()));

        // 设置分期是否完结
        //model.setIsFinishPerformance(true);

        // 设置外部分期单号
        model.setOutInstallmentOrderId(bill.getTransactionId());

        // 设置外部商户订单号
        model.setOutOrderId(bill.getOrderCode());

        // 设置分期阶段编码
        model.setStageNo(bill.getStageNo());

        // 设置分期单支付渠道
        String payChannel = "OTHER";
        String tradeNo = bill.getTradeNo();
        if (ToolUtils.isNotEmpty(tradeNo)) {
            payChannel = "ALIPAY";
            model.setTradeNo(tradeNo);
        }
        model.setPayChannel(payChannel);

        request.setBizModel(model);
        try {
            AlipayOpenMiniOrderInstallmentCreateResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("订单分期调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("订单分期调用失败，诊断链接：{}", diagnosisUrl);
            }
            return response;
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("订单分期调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 单笔转账 https://opendocs.alipay.com/apis/009zav?scene=ca56bca529e64125a2786703c6192d41
     * @Date 2024/9/22 9:43
     * @Author YWX
     * @Param [outBizNo, amount, orderTitle, payeeIdentity, payeeRealName, remark]
     * @Return void
     **/
    public static String alipayFundTransUniTransfer(String outBizNo, String amount, String orderTitle, String payeeIdentity, String payeeRealName, String remark) {
        // 构造请求参数以调用接口
        AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
        request.setNotifyUrl(ConfigKey.notifyUrl);
        AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();

        // 设置商家侧唯一订单号
        model.setOutBizNo(outBizNo);

        // 设置订单总金额
        model.setTransAmount(amount);

        // 设置描述特定的业务场景（单笔无密转账固定为 DIRECT_TRANSFER）
        model.setBizScene("DIRECT_TRANSFER");

        // 设置业务产品码（单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD）
        model.setProductCode("TRANS_ACCOUNT_NO_PWD");

        // 设置转账业务的标题
        model.setOrderTitle(orderTitle);

        // 设置收款方信息
        Participant payeeInfo = new Participant();
        //payeeInfo.setCertType("IDENTITY_CARD");
        //payeeInfo.setCertNo("1201152******72917");
        //标识（支付宝登录号，支持邮箱和手机号格式）
        payeeInfo.setIdentity(payeeIdentity);
        //参与方真实姓名（将校验收款支付宝账号姓名一致性）
        payeeInfo.setName(payeeRealName);
        //标识类型（支付宝登录号）
        payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
        model.setPayeeInfo(payeeInfo);

        // 设置业务备注
        model.setRemark(remark);

        // 设置转账业务请求的扩展参数
        model.setBusinessParams("{\"payer_show_name_use_alias\":\"true\"}");

        request.setBizModel(model);
        try {
            AlipayFundTransUniTransferResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("单笔转账调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("单笔转账调用失败，诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
            return response.getOrderId();
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("单笔转账失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 统一收单线下交易预创建 https://opendocs.alipay.com/open/8ad49e4a_alipay.trade.precreate?pathHash=d18bff53&scene=2ae8516856f24a5592194d237f3f235d&ref=api
     * @Date 2024/9/22 10:01
     * @Author YWX
     * @Param [outTradeNo, amount, orderTitle]
     * @Return void
     **/
    public static String alipayTradePrecreate(String outTradeNo, String amount, String orderTitle) {
        // 构造请求参数以调用接口
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
        request.setNotifyUrl(ConfigKey.notifyUrl);
        AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();

        // 设置商户订单号
        model.setOutTradeNo(outTradeNo);

        // 设置订单总金额
        model.setTotalAmount(amount);

        // 设置订单标题
        model.setSubject(orderTitle);

        // 设置产品码（订单码支付传：QR_CODE_OFFLINE）
        model.setProductCode("QR_CODE_OFFLINE");

        // 设置卖家支付宝用户ID
        /*model.setSellerId("2088102146225135");

        // 设置订单附加信息
        model.setBody("Iphone6 16G");

        // 设置订单包含的商品列表信息
        List<GoodsDetail> goodsDetail = new ArrayList<>();
        GoodsDetail goodsDetail0 = new GoodsDetail();
        goodsDetail0.setGoodsName("ipad");
        goodsDetail0.setQuantity(1L);
        goodsDetail0.setPrice("2000");
        goodsDetail0.setGoodsId("apple-01");
        goodsDetail0.setGoodsCategory("34543238");
        goodsDetail0.setCategoriesTree("124868003|126232002|126252004");
        goodsDetail0.setShowUrl("http://www.alipay.com/xxx.jpg");
        goodsDetail.add(goodsDetail0);
        model.setGoodsDetail(goodsDetail);

        // 设置业务扩展参数
        ExtendParams extendParams = new ExtendParams();
        extendParams.setSysServiceProviderId("2088511833207846");
        model.setExtendParams(extendParams);

        // 设置商户传入业务信息
        BusinessParams businessParams = new BusinessParams();
        businessParams.setMcCreateTradeIp("127.0.0.1");
        model.setBusinessParams(businessParams);

        // 设置可打折金额
        model.setDiscountableAmount("80.00");

        // 设置商户门店编号
        model.setStoreId("NJ_001");

        // 设置商户操作员编号
        model.setOperatorId("yx_001");

        // 设置商户机具终端编号
        model.setTerminalId("NJ_T_001");

        // 设置商户的原始订单号
        model.setMerchantOrderNo("20161008001");*/

        request.setBizModel(model);
        // 第三方代调用模式下请设置app_auth_token
        // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");

        try {
            AlipayTradePrecreateResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("统一收单线下交易预创建调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("统一收单线下交易预创建调用失败，诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
            return response.getQrCode();
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("统一收单线下交易预创建失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 初始化身份认证单据号
     * @Date 2024/9/25 21:45
     * @Author YWX
     * @Param [orderCode, certName, certNo]
     * @Return java.lang.String
     **/
    public static String alipayUserCertifyOpenInitialize(String certName, String certNo) {
        // 构造请求参数以调用接口
        AlipayUserCertifyOpenInitializeRequest request = new AlipayUserCertifyOpenInitializeRequest();
        AlipayUserCertifyOpenInitializeModel model = new AlipayUserCertifyOpenInitializeModel();

        // 设置认证场景码
        model.setBizCode("FACE");

        // 设置身份信息
        OpenCertifyIdentityParam identityParam = new OpenCertifyIdentityParam();
        identityParam.setCertType("IDENTITY_CARD");
        identityParam.setCertName(certName);
        identityParam.setCertNo(certNo);
        identityParam.setIdentityType("CERT_INFO");
        model.setIdentityParam(identityParam);

        // 设置商户请求的唯一标识
        model.setOuterOrderNo(CodeUtil.generateOuterOrderNo());

        // 设置商户个性化配置
        OpenCertifyMerchantConfig merchantConfig = new OpenCertifyMerchantConfig();
        merchantConfig.setFaceReserveStrategy("reserve");
        merchantConfig.setReturnUrl("");
        model.setMerchantConfig(merchantConfig);

        request.setBizModel(model);
        // 第三方代调用模式下请设置app_auth_token
        // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");

        try {
            AlipayUserCertifyOpenInitializeResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("化身份认证单据号调用成功，返回值：{}", response.getBody());

            if (response.isSuccess()) {
                return response.getCertifyId();
            } else {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("化身份认证单据号失败，诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("化身份认证单据号失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 生成认证URL
     * @Date 2024/9/25 21:50
     * @Author YWX
     * @Param [certifyId]
     * @Return java.lang.String
     **/
    public static String alipayUserCertifyOpenCertify(String certifyId) {
        // 构造请求参数以调用接口
        AlipayUserCertifyOpenCertifyRequest request = new AlipayUserCertifyOpenCertifyRequest();
        AlipayUserCertifyOpenCertifyModel model = new AlipayUserCertifyOpenCertifyModel();

        // 设置本次申请操作的唯一标识
        model.setCertifyId(certifyId);

        request.setBizModel(model);
        // 第三方代调用模式下请设置app_auth_token
        // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");

        try {
            //AlipayUserCertifyOpenCertifyResponse response = alipayClient.pageExecute(request, "POST");
            // 如果需要返回GET请求，请使用
            AlipayUserCertifyOpenCertifyResponse response = AlipayCreate.alipayClient.pageExecute(request, "GET");
            String pageRedirectionData = response.getBody();
            AlipayCreate.log.info("生成认证URL调用成功，返回值：{}", pageRedirectionData);

            if (response.isSuccess()) {
                return pageRedirectionData;
            } else {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("生成认证URL失败，诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("生成认证URL失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 查询身份认证结果
     * @Date 2024/9/25 22:01
     * @Author YWX
     * @Param [certifyId]
     * @Return java.lang.String
     **/
    public static Integer alipayUserCertifyOpenQuery(String certifyId) {
        // 构造请求参数以调用接口
        AlipayUserCertifyOpenQueryRequest request = new AlipayUserCertifyOpenQueryRequest();
        AlipayUserCertifyOpenQueryModel model = new AlipayUserCertifyOpenQueryModel();

        // 设置本次申请操作的唯一标识
        model.setCertifyId(certifyId);

        request.setBizModel(model);
        // 第三方代调用模式下请设置app_auth_token
        // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");

        int certifyPassed;
        try {
            AlipayUserCertifyOpenQueryResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("查询身份认证结果调用成功，返回值：{}", response.getBody());

            if (response.isSuccess()) {
                if ("T".equals(response.getPassed())) {
                    certifyPassed = 1;
                } else {
                    certifyPassed = 2;
                }
                return certifyPassed;
            } else {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("查询身份认证结果调用失败，诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("查询身份认证结果调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 预授权支付
     * @Date 2024/9/27 17:19
     * @Author YWX
     * @Param [outTradeNo, authNo, goodsName, totalAmount]
     * @Return void
     **/
    public static AlipayTradePayResponse alipayTradePay(String outTradeNo, String authNo, String subject, Double totalAmount) {
        // 构造请求参数以调用接口
        AlipayTradePayRequest request = new AlipayTradePayRequest();
        request.setNotifyUrl(ConfigKey.notifyUrl);
        AlipayTradePayModel model = new AlipayTradePayModel();

        // 设置商户订单号
        model.setOutTradeNo(outTradeNo);

        // 设置订单总金额
        model.setTotalAmount(ToolUtils.objToString(totalAmount));

        // 设置订单标题
        model.setSubject(subject);

        // 设置产品码
        model.setProductCode("PREAUTH_PAY");

        // 设置资金预授权单号
        model.setAuthNo(authNo);

        // 设置预授权确认模式（COMPLETE：转交易完成后解冻剩余冻结金额；NOT_COMPLETE：转交易完成后不解冻剩余冻结金额，默认值为：NOT_COMPLETE）
        model.setAuthConfirmMode("NOT_COMPLETE");

        // 设置返回参数选项
        List<String> queryOptions = new ArrayList<>();
        queryOptions.add("voucher_detail_list");
        model.setQueryOptions(queryOptions);

        request.setBizModel(model);

        try {
            AlipayTradePayResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("预授权支付调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("预授权支付调用失败，诊断链接：{}", diagnosisUrl);
            }
            return response;
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("预授权支付调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 预授权支付回传appid（发起代扣）
     * @Date 2024/11/16 18:25
     * @Author YWX
     * @Param [outTradeNo, authNo, subject, totalAmount]
     * @Return com.alipay.api.response.AlipayTradePayResponse
     **/
    public static AlipayTradePayResponse alipayTradePay3(String outTradeNo, String authNo, String subject, String body, Double totalAmount
            , String installmentOrderId, String tradeComponentOrderId, GoodsDetail gd) {
        if (ToolUtils.isEmpty(authNo)) {
            throw new ServiceException("预授权单号不能为空");
        }
        // 构造请求参数以调用接口
        AlipayTradePayRequest request = new AlipayTradePayRequest();
        request.setNotifyUrl(ConfigKey.notifyUrl);
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", outTradeNo);
        bizContent.put("total_amount", totalAmount);
        bizContent.put("subject", subject);
        bizContent.put("auth_no", authNo);
        bizContent.put("product_code", "PREAUTH_PAY");
        // 新增 business_params 扩展参数
        JSONObject businessParams = new JSONObject();
        businessParams.put("tinyAppId", ConfigKey.appId);
        bizContent.put("business_params", businessParams);
        // 新增 extend_params 扩展参数
        JSONObject extendParams = new JSONObject();
        extendParams.put("merchant_tiny_app_id", ConfigKey.appId);
        if (ToolUtils.isNotEmpty(installmentOrderId)) {
            extendParams.put("trade_component_order_id", tradeComponentOrderId);
            extendParams.put("tc_installment_order_id", installmentOrderId);
        }
        bizContent.put("extend_params", extendParams);

        //订单包含的商品列表信息
        List<Map> goodsDetail = new ArrayList<>();
        Map<String, Object> goodsMap = new HashMap<>();
        goodsMap.put("goods_id", gd.getGoodsId());
        goodsMap.put("goods_name", gd.getGoodsName());
        goodsMap.put("quantity", gd.getQuantity());
        goodsMap.put("price", gd.getPrice());
        goodsMap.put("goods_category", gd.getGoodsCategory());
        goodsMap.put("categories_tree", gd.getCategoriesTree());
        goodsMap.put("show_url", gd.getShowUrl());
        goodsDetail.add(goodsMap);
        bizContent.put("goods_detail", goodsDetail);

        bizContent.put("body", "小程序：" + ConfigKey.appName + "；" + body);

        request.setBizContent(JSON.toJSONString(bizContent));

        try {
            AlipayTradePayResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("账单交易流水号：{} 查询押金转支付结果：{}", outTradeNo, response.getBody());
            return response;
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("账单交易流水号：{} 查询押金转支付失败：{}", outTradeNo, e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 统一收单交易余额支付创建
     * @Date 2024/9/30 17:12
     * @Author YWX
     * @Param [outTradeNo, authNo, subject, totalAmount]
     * @Return com.alipay.api.response.AlipayTradePayResponse
     **/
    public static AlipayTradePayResponse alipayTradePay2(String outTradeNo, String authNo, String subject, Double totalAmount) {
        // 构造请求参数以调用接口
        AlipayTradePayRequest request = new AlipayTradePayRequest();
        request.setNotifyUrl(ConfigKey.notifyUrl);
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", outTradeNo);
        bizContent.put("total_amount", totalAmount);
        bizContent.put("subject", subject);
        bizContent.put("auth_no", authNo);
        bizContent.put("product_code", "PREAUTH_PAY");
        bizContent.put("enable_pay_channels", "balance");//余额支付

        request.setBizContent(JSON.toJSONString(bizContent));

        try {
            AlipayTradePayResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            if (!response.isSuccess()) {
                throw new ServiceException(response.getSubMsg());
            }
            return response;
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("统一收单交易余额支付创建失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 查询对账单下载地址
     * @Date 2024/10/23 13:26
     * @Author YWX
     * @Param [billDate]
     * @Return com.alipay.api.response.AlipayDataDataserviceBillDownloadurlQueryResponse
     **/
    public static AlipayDataDataserviceBillDownloadurlQueryResponse billQuery(String billDate) {
        // 构造请求参数以调用接口
        AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();
        AlipayDataDataserviceBillDownloadurlQueryModel model = new AlipayDataDataserviceBillDownloadurlQueryModel();
        model.setBillType("trade");
        model.setBillDate(billDate);
        request.setBizModel(model);

        try {
            AlipayDataDataserviceBillDownloadurlQueryResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            //AlipayCreate.log.info("查询对账单下载地址成功，返回值：{}", response.getBody());
            if (!response.isSuccess()) {
                throw new ServiceException(response.getSubMsg());
            }
            return response;
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("查询对账单下载地址失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 创建商家券活动 https://opendocs.alipay.com/pre-open/0290rn?pathHash=b545088e&scene=a0667e04ac87431eb7e6adc5f13cc8ba
     * @Date 2024/11/15 23:59
     * @Author YWX
     * @Param [coupon]
     * @Return com.alipay.api.response.AlipayMarketingActivityOrdervoucherCreateResponse
     **/
    public static AlipayMarketingActivityOrdervoucherCreateResponse addCoupon(TCoupon coupon, Map<String, Object> extendParams) {
        // 初始化SDK
        try {
            // 构造请求参数以调用接口
            AlipayMarketingActivityOrdervoucherCreateRequest request = new AlipayMarketingActivityOrdervoucherCreateRequest();
            AlipayMarketingActivityOrdervoucherCreateModel model = new AlipayMarketingActivityOrdervoucherCreateModel();

            // 设置活动基础信息
            ActivityBaseInfo activityBaseInfo = new ActivityBaseInfo();
            activityBaseInfo.setActivityName(coupon.getName());
            activityBaseInfo.setCodeMode("MERCHANT_UPLOAD");
            model.setActivityBaseInfo(activityBaseInfo);

            // 设置商户接入模式
            model.setMerchantAccessMode("SELF_MODE");

            // 设置外部业务单号
            model.setOutBizNo(CodeUtil.generateOuterOrderNo());

            // 设置券可用范围
            VoucherAvailableScopeInfo voucherAvailableScopeInfo = new VoucherAvailableScopeInfo();
            VoucherAvailableGeographyScopeInfo voucherAvailableGeographyScopeInfo = new VoucherAvailableGeographyScopeInfo();
            VoucherAvailableGeographyCityInfo availableGeographyCityInfo = new VoucherAvailableGeographyCityInfo();
            availableGeographyCityInfo.setAllCity(true);
            voucherAvailableGeographyScopeInfo.setAvailableGeographyCityInfo(availableGeographyCityInfo);
            voucherAvailableGeographyScopeInfo.setAvailableGeographyScopeType("CITY_CODE");
            voucherAvailableScopeInfo.setVoucherAvailableGeographyScopeInfo(voucherAvailableGeographyScopeInfo);
            //券可用商品（限品、特价券必传）
            VoucherAvailableGoodsInfo voucherAvailableGoodsInfo = new VoucherAvailableGoodsInfo();
            String goodsName = ToolUtils.objToString(extendParams.get("goodsName"));
            if (ToolUtils.isNotEmpty(goodsName) && goodsName.length() > 12) {
                goodsName = goodsName.substring(0, 12);
            }
            voucherAvailableGoodsInfo.setGoodsName(goodsName);
            voucherAvailableGoodsInfo.setOriginAmount(ToolUtils.objToString(extendParams.get("originAmount")));
            voucherAvailableScopeInfo.setVoucherAvailableGoodsInfo(voucherAvailableGoodsInfo);
            model.setVoucherAvailableScopeInfo(voucherAvailableScopeInfo);

            // 设置券引导详情
            VoucherCustomerGuideInfo voucherCustomerGuideInfo = new VoucherCustomerGuideInfo();
            VoucherUseGuideInfo voucherUseGuideInfo = new VoucherUseGuideInfo();
            VoucherMiniAppUseGuideInfo miniAppUseGuideInfo = new VoucherMiniAppUseGuideInfo();
            miniAppUseGuideInfo.setMiniAppUrl("alipays://platformapi/startapp?appId=" + ConfigKey.appId);
            voucherUseGuideInfo.setMiniAppUseGuideInfo(miniAppUseGuideInfo);
            List<String> useGuideMode = new ArrayList<>();
            useGuideMode.add("MINI_APP");//小程序线上核销
            voucherUseGuideInfo.setUseGuideMode(useGuideMode);
            voucherCustomerGuideInfo.setVoucherUseGuideInfo(voucherUseGuideInfo);
            model.setVoucherCustomerGuideInfo(voucherCustomerGuideInfo);

            // 设置券优惠抵扣信息
            VoucherDeductInfo voucherDeductInfo = new VoucherDeductInfo();
            String voucherType;
            Integer couponType = coupon.getCouponType();
            Integer category = coupon.getCategory();//优惠券品类（1抵扣券2折扣券3特价券）
            if (category.equals(1)) {
                voucherType = "FIX_VOUCHER";
                //满减券详情
                FixVoucherInfo fixVoucherInfo = new FixVoucherInfo();
                fixVoucherInfo.setAmount(ToolUtils.objToString(coupon.getMoney()));//券面额：[0.1,3000]
                fixVoucherInfo.setFloorAmount(ToolUtils.objToString(coupon.getLimitMoney()));//门槛金额：[0.1,50000];该字段不填写，认为无门槛
                voucherDeductInfo.setFixVoucherInfo(fixVoucherInfo);
            } else if (category.equals(2)) {
                voucherType = "DISCOUNT_VOUCHER";
                //折扣券详情
                DiscountVoucherInfo discountVoucherInfo = new DiscountVoucherInfo();
                discountVoucherInfo.setCeilingAmount(ToolUtils.objToString(coupon.getCeilingAmount()));
                discountVoucherInfo.setDiscount(ToolUtils.objToString(coupon.getMoney()));//折扣率：[0.1,9.9]
                discountVoucherInfo.setFloorAmount(ToolUtils.objToString(coupon.getLimitMoney()));//门槛金额：[0.1,50000];该字段不填写，认为无门槛
                discountVoucherInfo.setCeilingAmount(ToolUtils.objToString(coupon.getCeilingAmount()));
                voucherDeductInfo.setDiscountVoucherInfo(discountVoucherInfo);
            } else {
                voucherType = "SPECIAL_VOUCHER";
                SpecialVoucherInfo specialVoucherInfo = new SpecialVoucherInfo();
                specialVoucherInfo.setSpecialAmount(ToolUtils.objToString(coupon.getMoney()));//券面额：[0.1,3000]
                specialVoucherInfo.setFloorAmount(ToolUtils.objToString(coupon.getLimitMoney()));//门槛金额：[0.1,50000];该字段不填写，认为无门槛
                voucherDeductInfo.setSpecialVoucherInfo(specialVoucherInfo);
            }
            voucherDeductInfo.setVoucherType(voucherType);
            model.setVoucherDeductInfo(voucherDeductInfo);

            // 设置券展示信息
            VoucherDisplayPatternInfo voucherDisplayPatternInfo = new VoucherDisplayPatternInfo();
            voucherDisplayPatternInfo.setBrandLogo(ToolUtils.objToString(extendParams.get("resourceId")));
            voucherDisplayPatternInfo.setBrandName(ToolUtils.objToString(extendParams.get("storename")));
            voucherDisplayPatternInfo.setVoucherDescription(coupon.getComm());
            voucherDisplayPatternInfo.setCustomerServiceMobile(ToolUtils.objToString(extendParams.get("servicePhone")));
            model.setVoucherDisplayPatternInfo(voucherDisplayPatternInfo);

            // 设置券发放模式信息
            VoucherSendModeInfo voucherSendModeInfo = new VoucherSendModeInfo();
            voucherSendModeInfo.setVoucherSendMode("DIRECT_SEND_MODE");
            //券发放规则
            VoucherSendRuleInfo voucherSendRuleInfo = new VoucherSendRuleInfo();
            voucherSendRuleInfo.setPublishStartTime(coupon.getPublishStartTime());
            voucherSendRuleInfo.setPublishEndTime(coupon.getPublishEndTime());
            voucherSendRuleInfo.setQuantity(0L);
            voucherSendRuleInfo.setQuantityLimitPerUser(Long.valueOf(coupon.getLimitNum()));
            voucherSendRuleInfo.setNaturalPersonLimit(false);
            voucherSendModeInfo.setVoucherSendRuleInfo(voucherSendRuleInfo);
            model.setVoucherSendModeInfo(voucherSendModeInfo);

            // 设置券核销限制
            VoucherUseRuleInfo voucherUseRuleInfo = new VoucherUseRuleInfo();
            VoucherUseTimeInfo voucherUseTimeInfo = new VoucherUseTimeInfo();
            String periodType;
            if (coupon.getLimitType().equals(1)) {//相对期限
                periodType = "RELATIVE";
                VoucherRelativePeriodInfo relativePeriodInfo = new VoucherRelativePeriodInfo();
                relativePeriodInfo.setWaitDaysAfterReceive(0L);
                relativePeriodInfo.setValidDaysAfterReceive(Long.valueOf(coupon.getLimitDay()));
                voucherUseTimeInfo.setRelativePeriodInfo(relativePeriodInfo);
            } else {//固定期限
                periodType = "ABSOLUTE";
                VoucherAbsolutePeriodInfo absolutePeriodInfo = new VoucherAbsolutePeriodInfo();
                absolutePeriodInfo.setValidBeginTime(ToolUtils.localDateTimeToDate(coupon.getUseTimeBegin()));
                absolutePeriodInfo.setValidEndTime(ToolUtils.localDateTimeToDate(coupon.getUseTimeEnd()));
                voucherUseTimeInfo.setAbsolutePeriodInfo(absolutePeriodInfo);
            }
            voucherUseTimeInfo.setPeriodType(periodType);
            voucherUseRuleInfo.setVoucherUseTimeInfo(voucherUseTimeInfo);
            model.setVoucherUseRuleInfo(voucherUseRuleInfo);

            request.setBizModel(model);
            AlipayMarketingActivityOrdervoucherCreateResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("创建商家券活动调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("创建商家券活动调用失败，诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
            return response;
        } catch (Exception e) {
            AlipayCreate.log.error("创建商家券活动失败：{}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    //修改商家券活动基本信息
    public static AlipayMarketingActivityOrdervoucherModifyResponse modifyCoupon(TCoupon coupon, Map<String, Object> extendParams) {
        // 初始化SDK
        try {
            // 构造请求参数以调用接口
            AlipayMarketingActivityOrdervoucherModifyRequest request = new AlipayMarketingActivityOrdervoucherModifyRequest();
            AlipayMarketingActivityOrdervoucherModifyModel model = new AlipayMarketingActivityOrdervoucherModifyModel();

            // 活动信息
            model.setActivityId(coupon.getActivityId());
            model.setActivityName(coupon.getName());
            model.setPublishStartTime(coupon.getPublishStartTime());
            model.setPublishEndTime(coupon.getPublishEndTime());

            // 设置外部业务单号
            model.setOutBizNo(CodeUtil.generateOuterOrderNo());

            //券发放规则
            VoucherSendRuleDetailModify voucherSendRuleInfo = new VoucherSendRuleDetailModify();
            voucherSendRuleInfo.setVoucherQuantityLimitPerUser(Long.valueOf(coupon.getLimitNum()));
            voucherSendRuleInfo.setNaturalPersonLimit(false);
            model.setVoucherSendRule(voucherSendRuleInfo);

            // 设置券展示信息
            VoucherDisplayPatternInfo voucherDisplayPatternInfo = new VoucherDisplayPatternInfo();
            voucherDisplayPatternInfo.setBrandLogo(ToolUtils.objToString(extendParams.get("resourceId")));
            voucherDisplayPatternInfo.setBrandName(ToolUtils.objToString(extendParams.get("storename")));
            voucherDisplayPatternInfo.setVoucherDescription(coupon.getComm());
            voucherDisplayPatternInfo.setCustomerServiceMobile(ToolUtils.objToString(extendParams.get("servicePhone")));
            model.setVoucherDisplayPatternInfo(voucherDisplayPatternInfo);

            request.setBizModel(model);
            AlipayMarketingActivityOrdervoucherModifyResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("修改商家券活动调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("修改商家券活动调用失败，诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
            return response;
        } catch (Exception e) {
            AlipayCreate.log.error("修改商家券活动失败：{}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    //修改商家券活动发券数量上限
    public static void modifyCouponNum(String activityId, Integer num) {
        // 初始化SDK
        try {
            // 构造请求参数以调用接口
            AlipayMarketingActivityOrdervoucherAppendRequest request = new AlipayMarketingActivityOrdervoucherAppendRequest();
            AlipayMarketingActivityOrdervoucherAppendModel model = new AlipayMarketingActivityOrdervoucherAppendModel();

            // 设置发行券的数量
            model.setVoucherQuantity(ToolUtils.objToLong(num));
            // 设置活动 id
            model.setActivityId(activityId);

            // 设置外部业务单号
            model.setOutBizNo(CodeUtil.generateOuterOrderNo());

            // 设置商户接入模式
            model.setMerchantAccessMode("SELF_MODE");

            request.setBizModel(model);
            AlipayMarketingActivityOrdervoucherAppendResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("修改商家券数量调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("修改商家券数量调用失败，诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
        } catch (Exception e) {
            AlipayCreate.log.error("修改商家券数量失败：{}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    //停止商家券活动
    public static void stoppedCoupon(String activityId) {
        // 初始化SDK
        try {
            AlipayMarketingActivityOrdervoucherStopRequest request = new AlipayMarketingActivityOrdervoucherStopRequest();
            AlipayMarketingActivityOrdervoucherStopModel model = new AlipayMarketingActivityOrdervoucherStopModel();

            // 设置活动 id
            model.setActivityId(activityId);

            // 设置外部业务单号
            model.setOutBizNo(CodeUtil.generateOuterOrderNo());

            // 设置商户接入模式
            model.setMerchantAccessMode("SELF_MODE");

            request.setBizModel(model);
            AlipayMarketingActivityOrdervoucherStopResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("停止商家券活动调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("停止商家券活动调用失败，诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
        } catch (Exception e) {
            AlipayCreate.log.error("停止商家券活动失败：{}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    //同步券核销状态
    public static void useCoupon(Map<String, String> coupon) {
        // 初始化SDK
        try {
            // 构造请求参数以调用接口
            AlipayMarketingActivityOrdervoucherUseRequest request = new AlipayMarketingActivityOrdervoucherUseRequest();
            AlipayMarketingActivityOrdervoucherUseModel model = new AlipayMarketingActivityOrdervoucherUseModel();

            // 设置活动 id
            model.setActivityId(coupon.get("activityId"));

            // 设置外部优惠券的核销时间
            model.setBizDt(ToolUtils.localDateTimeToDate(LocalDateTime.now()));

            // 设置外部业务单号
            model.setOutBizNo(CodeUtil.generateOuterOrderNo());

            // 设置订单优惠前的总金额
            model.setTotalFee(coupon.get("totalFee"));

            // 设置交易渠道
            model.setTradeChannel("OTHER_TRADE_CHANNEL");

            // 设置券码
            model.setVoucherCode(coupon.get("voucherCode"));

            request.setBizModel(model);
            AlipayMarketingActivityOrdervoucherUseResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("同步券核销状态调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("同步券核销状态调用失败，诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
        } catch (Exception e) {
            AlipayCreate.log.error("同步券核销状态失败：{}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    //取消券核销状态
    public static void refundCoupon(Map<String, String> coupon) {
        // 初始化SDK
        try {
            // 构造请求参数以调用接口
            AlipayMarketingActivityOrdervoucherRefundRequest request = new AlipayMarketingActivityOrdervoucherRefundRequest();
            AlipayMarketingActivityOrdervoucherRefundModel model = new AlipayMarketingActivityOrdervoucherRefundModel();

            // 设置活动 id
            model.setActivityId(coupon.get("activityId"));

            // 当前订单的退券时间
            model.setBizDt(ToolUtils.localDateTimeToDate(LocalDateTime.now()));

            // 设置外部业务单号
            model.setOutBizNo(CodeUtil.generateOuterOrderNo());

            // 设置券码
            model.setVoucherCode(coupon.get("voucherCode"));

            request.setBizModel(model);
            AlipayMarketingActivityOrdervoucherRefundResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("取消券核销状态调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("取消券核销状态调用失败，诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
        } catch (Exception e) {
            AlipayCreate.log.error("取消券核销状态失败：{}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    //同步商家券券码
    public static void syncCoupon(String activityId, List<String> voucherCodes) {
        // 初始化SDK
        try {
            // 构造请求参数以调用接口
            AlipayMarketingActivityOrdervoucherCodedepositRequest request = new AlipayMarketingActivityOrdervoucherCodedepositRequest();
            AlipayMarketingActivityOrdervoucherCodedepositModel model = new AlipayMarketingActivityOrdervoucherCodedepositModel();

            // 设置券码列表
            model.setVoucherCodes(voucherCodes);

            // 设置活动 id
            model.setActivityId(activityId);

            // 设置外部业务单号
            model.setOutBizNo(CodeUtil.generateOuterOrderNo());

            // 设置商户接入模式
            model.setMerchantAccessMode("SELF_MODE");

            request.setBizModel(model);
            AlipayMarketingActivityOrdervoucherCodedepositResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("同步商家券券码调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("同步商家券券码调用失败，诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
        } catch (Exception e) {
            AlipayCreate.log.error("同步商家券券码失败：{}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    //统计商家券券码数量
    public static void countCoupon(String activityId) {
        // 初始化SDK
        try {
            // 构造请求参数以调用接口
            AlipayMarketingActivityOrdervoucherCodecountRequest request = new AlipayMarketingActivityOrdervoucherCodecountRequest();
            AlipayMarketingActivityOrdervoucherCodecountModel model = new AlipayMarketingActivityOrdervoucherCodecountModel();

            // 设置活动 id
            model.setActivityId(activityId);

            // 设置商户接入模式
            model.setMerchantAccessMode("SELF_MODE");

            request.setBizModel(model);
            AlipayMarketingActivityOrdervoucherCodecountResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("统计商家券券码数量调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("统计商家券券码数量调用失败，诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
        } catch (Exception e) {
            AlipayCreate.log.error("统计商家券券码数量失败：{}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    //活动领取咨询
    public static List<Map> activityConsult(List<String> activityIds, String openId) {
        // 初始化SDK
        try {
            // 构造请求参数以调用接口
            AlipayMarketingActivityConsultRequest request = new AlipayMarketingActivityConsultRequest();
            AlipayMarketingActivityConsultModel model = new AlipayMarketingActivityConsultModel();

            // 设置活动 id
            List<ConsultActivityInfo> consultActivityInfoList = new ArrayList<>();
            for (String activityId : activityIds) {
                ConsultActivityInfo consultActivityInfoList0 = new ConsultActivityInfo();
                consultActivityInfoList0.setActivityId(activityId);
                consultActivityInfoList.add(consultActivityInfoList0);
            }
            model.setConsultActivityInfoList(consultActivityInfoList);

            // 设置商户接入模式
            model.setMerchantAccessMode("SELF_MODE");
            model.setOpenId(openId);

            request.setBizModel(model);
            AlipayMarketingActivityConsultResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("活动领取咨询调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("活动领取咨询调用失败，诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
            List<Map> result = new ArrayList<>();
            for (ConsultActivityResultInfo info : response.getConsultResultInfoList()) {
                if ("SUCCESS".equals(info.getConsultResultCode())) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("activityId", info.getActivityId());
                    map.put("outBizNo", CodeUtil.generateOuterOrderNo());
                    result.add(map);
                }
            }
            return result;
        } catch (Exception e) {
            AlipayCreate.log.error("活动领取咨询失败：{}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    //营销图片资源上传
    public static String logoUpload(String storelogo) {
        // 初始化SDK
        try {
            URL url = new URL(storelogo);
            InputStream inputStream = url.openStream();
            String filename = storelogo.substring(storelogo.lastIndexOf("/") + 1);
            // 下列FileItem中也可用直接读取本地文件的方式来获取文件
            FileItem imageContent = new FileItem(filename, inputStream.readAllBytes());

            // 构造请求参数以调用接口
            AlipayMarketingMaterialImageUploadRequest request = new AlipayMarketingMaterialImageUploadRequest();

            request.setFileContent(imageContent);

            // 设置文件业务标识
            request.setFileKey("PROMO_BRAND_LOGO");

            // 设置商户接入模式
            request.setMerchantAccessMode("SELF_MODE");

            AlipayMarketingMaterialImageUploadResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("营销图片资源上传调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("营销图片资源上传调用失败，诊断链接：{}", diagnosisUrl);
                throw new ServiceException(response.getSubMsg());
            }
            return response.getResourceId();
        } catch (Exception e) {
            AlipayCreate.log.error("营销图片资源上传失败：{}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * @Description 商品免审更新
     * @Date 2024/12/11 8:40
     * @Author YWX
     * @Param [goods]
     * @Return void
     **/
    public static boolean goodsDirectModify(TGoods goods) {
        // 构造请求参数以调用接口
        AlipayOpenAppItemDirectModifyRequest request = new AlipayOpenAppItemDirectModifyRequest();
        AlipayOpenAppItemDirectModifyModel model = new AlipayOpenAppItemDirectModifyModel();

        // 设置商家侧商品ID
        model.setOutItemId(ToolUtils.objToString(goods.getGoodsCode()));
        double multiply = ToolUtils.multiply(goods.getPriceRange().split("-")[0], 100);
        model.setSalePrice(ToolUtils.objToLong(multiply));
        String saleStatus = "DELISTING";
        if (!goods.getStock().equals(0)) {
            saleStatus = "AVAILABLE";
        }
        model.setSaleStatus(saleStatus);
        model.setStockNum(ToolUtils.objToLong(goods.getStock()));

        // 设置sku数组
        /*List<ItemDirectModifySku> skus = new ArrayList<>();
        for (TGoodsSpecs spec : goods.getSpecs()) {
            ItemDirectModifySku skus0 = new ItemDirectModifySku();
            skus0.setOutSkuId(model.getOutItemId() + "_" + ToolUtils.objToString(spec.getGsid()));
            skus0.setStockNum(Long.valueOf(spec.getStock()));
            String saleStatus = "DELISTING";
            if (spec.getOutStock().equals(0)) {
                saleStatus = "AVAILABLE";
            }
            skus0.setSaleStatus(saleStatus);
            skus0.setSalePrice(spec.getBuyPrice().longValue());
            skus.add(skus0);
        }
        model.setSkus(skus);*/

        request.setBizModel(model);

        try {
            AlipayOpenAppItemDirectModifyResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("商品免审更新调用成功，返回值：{}", response.getBody());

            boolean result = false;
            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("商品免审更新调用失败, 诊断链接：{}", diagnosisUrl);
                if (response.getSubMsg().contains("商品不存在")) {
                    result = true;
                }
            }
            return result;
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("商品免审更新调用失败：{}", e.getMessage());
            return false;
        }
    }

    //查询消息订阅关系
    public static boolean messagetemplateSubscribeQuery(String openId, List<String> templateIdList) {
        // 构造请求参数以调用接口
        AlipayOpenAppMessagetemplateSubscribeQueryRequest request = new AlipayOpenAppMessagetemplateSubscribeQueryRequest();
        AlipayOpenAppMessagetemplateSubscribeQueryModel model = new AlipayOpenAppMessagetemplateSubscribeQueryModel();

        model.setOpenId(openId);
        model.setTemplateIdList(templateIdList);

        request.setBizModel(model);

        try {
            AlipayOpenAppMessagetemplateSubscribeQueryResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("查询消息订阅关系调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("查询消息订阅关系调用失败, 诊断链接：{}", diagnosisUrl);
            }
            return response.getShowComponent();
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("查询消息订阅关系调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    //会员卡查询
    public static AlipayMarketingCardQueryResponse cardQuery(String bizCardNo, String openId) {
        // 构造请求参数以调用接口
        AlipayMarketingCardQueryRequest request = new AlipayMarketingCardQueryRequest();
        AlipayMarketingCardQueryModel model = new AlipayMarketingCardQueryModel();

        // 设置卡号ID类型
        model.setTargetCardNoType("BIZ_CARD");

        // 设置支付宝业务卡号
        model.setTargetCardNo(bizCardNo);

        // 设置持卡人信息
        CardUserInfo cardUserInfo = new CardUserInfo();
        cardUserInfo.setOpenId(openId);
        model.setCardUserInfo(cardUserInfo);

        request.setBizModel(model);

        try {
            AlipayMarketingCardQueryResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("会员卡查询调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("会员卡查询调用失败, 诊断链接：{}", diagnosisUrl);
            }
            return response;
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("会员卡查询调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * @Description 会员卡删卡
     * @Date 2025/1/5 18:03
     * @Author YWX
     * @Param [bizCardNo]
     * @Return void
     **/
    public static void cardDelete(String bizCardNo) {
        // 构造请求参数以调用接口
        AlipayMarketingCardDeleteRequest request = new AlipayMarketingCardDeleteRequest();
        AlipayMarketingCardDeleteModel model = new AlipayMarketingCardDeleteModel();

        model.setOutSerialNo(CodeUtil.generateOuterOrderNo());
        // 设置支付宝业务卡号
        model.setTargetCardNo(bizCardNo);
        // 设置卡号ID类型
        model.setTargetCardNoType("BIZ_CARD");
        model.setReasonCode("USER_UNBUND");//用户解绑（可以重新绑定）

        request.setBizModel(model);

        try {
            AlipayMarketingCardDeleteResponse response = AlipayCreate.alipayClient.certificateExecute(request);
            AlipayCreate.log.info("会员卡删卡调用成功，返回值：{}", response.getBody());

            if (!response.isSuccess()) {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("会员卡删卡调用失败, 诊断链接：{}", diagnosisUrl);
            }
        } catch (AlipayApiException e) {
            AlipayCreate.log.error("会员卡删卡调用失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * 租赁智能风险咨询（智安盾基础版）
     *
     * @param openId   支付宝openid
     * @param outBizNo 商家系统订单号
     * @throws AlipayApiException
     */
    public static Map<String, String> alipayCommerceRentRiskConsult(String openId, String outBizNo) {
        // 构造请求参数以调用接口
        AlipayCommerceRentRiskConsultRequest request = new AlipayCommerceRentRiskConsultRequest();
        AlipayCommerceRentRiskConsultModel model = new AlipayCommerceRentRiskConsultModel();

        // 设置支付宝openid
        model.setAlipayOpenId(openId);

        // 设置风险业务场景
        model.setRiskBizScene("RENT_ORDER");

        // 设置外部单号
        model.setOutBizNo(outBizNo);
        request.setBizModel(model);

        AtomicReference<String> riskLevel = new AtomicReference<>();
        AtomicReference<String> riskScore = new AtomicReference<>();
        AtomicReference<String> totalRisk = new AtomicReference<>();
        AtomicReference<String> incrementRisk = new AtomicReference<>();
        try {
            AlipayCommerceRentRiskConsultResponse response = alipayClient.certificateExecute(request);
            if (response.isSuccess()) {
                AlipayCreate.log.info("订单号：{} 调用租赁智能风险咨询（智安盾基础版）成功", outBizNo);
                List<RentRiskInfoVO> riskList = response.getRiskInfos();
                for (RentRiskInfoVO riskInfoVO : riskList) {
                    String riskType = riskInfoVO.getRiskType();
                    AlipayCreate.log.info("订单号：{} 调用租赁智能风险咨询（智安盾基础版）风控类型为：{}", outBizNo, riskType);
                    riskInfoVO.getRiskItemList().forEach(riskItem -> {
                        String riskCode = riskItem.getRiskCode();
                        String level = riskItem.getRiskLevel();
                        if ("ORDER_CONCURRENT_RENT_RISK".equals(riskCode)) {
                            riskLevel.set(level);
                        } else if ("APP_TRADING_HEALTH_SCORE".equals(riskCode)) {
                            riskScore.set(level);
                        } else if ("APP_CONCURRENT_RENT_TOTAL_RISK".equals(riskCode)) {
                            totalRisk.set(level);
                        } else if ("APP_CONCURRENT_RENT_30D_INCREMENT_RISK".equals(riskCode)) {
                            incrementRisk.set(level);
                        }
                    });
                }
            } else {
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                AlipayCreate.log.error("租赁智能风险咨询（智安盾基础版）调用失败, 诊断链接：{}", diagnosisUrl);
            }
            AlipayCreate.log.info("订单号：{} 智安盾接入评级为:{} 交易健康值为:{} 小程序共租风险浓度:{} 小程序30日新增共租风险浓度:{}", outBizNo, riskLevel.get(), riskScore.get(), totalRisk.get(), incrementRisk.get());
        } catch (AlipayApiException ex) {
            AlipayCreate.log.error("订单号：{} 租赁智能风险咨询（智安盾基础版）调用失败：{}", outBizNo, ex.getMessage());
            throw new ServiceException(ex.getMessage());
        }
        Map<String, String> data = new HashMap<>();
        data.put("riskLevel", riskLevel.get());
        data.put("riskScore", riskScore.get());
        data.put("totalRisk", totalRisk.get());
        data.put("incrementRisk", incrementRisk.get());
        return data;
    }

}
